home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / Caphisto.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  9.6 KB  |  332 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "VirtualDub.h"
  19. #include <crtdbg.h>
  20. #include <windows.h>
  21. #include <vfw.h>
  22.  
  23. #include "resource.h"
  24. #include "oshelper.h"
  25. #include "vbitmap.h"
  26. #include "helpfile.h"
  27. #include "Histogram.h"
  28. #include "Error.h"
  29.  
  30. #include "caphisto.h"
  31.  
  32. extern LRESULT CALLBACK CaptureStatusCallback(HWND hWnd, int nID, LPCSTR lpsz);
  33.  
  34. ///////////////////////////////////////////////////////////////////////////
  35. //
  36. //    General capture histogram
  37. //
  38. ///////////////////////////////////////////////////////////////////////////
  39.  
  40. CaptureHistogram::CaptureHistogram(HWND hwndCapture, HDC hdcExample, int max_height)
  41.     :CaptureFrameSource(hwndCapture)
  42.     ,histo(hdcExample, max_height)
  43.     {
  44. }
  45.  
  46. CaptureHistogram::~CaptureHistogram() {
  47. }
  48.  
  49. void CaptureHistogram::Process(VIDEOHDR *pvhdr) {
  50.     const VBitmap& vbAnalyze = *Decompress(pvhdr);
  51.  
  52.     histo.Zero();
  53.  
  54.     if (vbAnalyze.depth == 32)
  55.         histo.Process(&vbAnalyze);
  56.     else if (vbAnalyze.depth == 24)
  57.         histo.Process24(&vbAnalyze);
  58.     else if (vbAnalyze.depth == 16)
  59.         histo.Process16(&vbAnalyze);
  60. }
  61.  
  62. void CaptureHistogram::Draw(HDC hdc, RECT& r) {
  63.     histo.Draw(hdc, &r);
  64. }
  65.  
  66. ///////////////////////////////////////////////////////////////////////////
  67. //
  68. //    Active histogram
  69. //
  70. ///////////////////////////////////////////////////////////////////////////
  71.  
  72. // VideoSource.cpp
  73. extern void DIBconvert(void *src, BITMAPINFOHEADER *srcfmt, void *dst, BITMAPINFOHEADER *dstfmt);
  74.  
  75. typedef struct HistogramDlgData {
  76.     HWND hDlg;
  77.     HWND hwndCapture; //, hwndStatus;
  78.     LONG fsize;
  79.     BITMAPINFOHEADER *bmih, bmihDecomp;
  80.     CAPTUREPARMS cp, cp_back;
  81.     UINT uTimer;
  82.     void *buffer;
  83.     HIC hic;
  84.     HDC hdc;
  85.     RECT rHisto;
  86.     VBitmap vbitmap;
  87.     Histogram *histo;
  88.  
  89.     BOOL fParmsSet, fCapture, fCaptureStupid, fCompressionOk;
  90. } HistogramDlgData;
  91.  
  92. LRESULT CALLBACK CaptureHistogramStatusCallbackProc(HWND hWnd, int nID, LPCSTR lpsz) {
  93.     HistogramDlgData *hdd = (HistogramDlgData *)capGetUserData(hWnd);
  94.  
  95.     switch(nID) {
  96.     case IDS_CAP_BEGIN:
  97.         hdd->fCapture = TRUE;
  98.         break;
  99.     case IDS_CAP_END:
  100.         hdd->fCapture = FALSE;
  101.         PostMessage(hdd->hDlg, WM_COMMAND, 0, 0);
  102.         break;
  103.     }
  104.  
  105.     return 0;
  106. }
  107.  
  108. static LRESULT CALLBACK CaptureHistogramVideoCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
  109. {
  110.     HistogramDlgData *hdd = (HistogramDlgData *)capGetUserData(hWnd);
  111.     DWORD err;
  112.     char buf[128];
  113.     CAPSTATUS capStatus;
  114.  
  115.     capGetStatus(hWnd, (LPARAM)&capStatus, sizeof(CAPSTATUS));
  116.  
  117.     hdd->bmih->biSizeImage = lpVHdr->dwBytesUsed;
  118.  
  119.     if (hdd->hic) {
  120.  
  121.         err = ICDecompress(
  122.                 hdd->hic,
  123.                 lpVHdr->dwFlags & VHDR_KEYFRAME ? AVIIF_KEYFRAME : 0,
  124.                 hdd->bmih,
  125.                 lpVHdr->lpData,
  126.                 &hdd->bmihDecomp,
  127.                 hdd->buffer);
  128.  
  129.         if (err != ICERR_OK) {
  130.             wsprintf(buf,"decompression error %08lx",err);
  131.             SendMessage(hdd->hDlg, WM_SETTEXT, 0, (LPARAM)buf);
  132. //            RedrawWindow(hdd->hwndStatus, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
  133.             return 0;
  134.         }
  135.  
  136.     } else {
  137.         DIBconvert(lpVHdr->lpData, hdd->bmih, hdd->buffer, &hdd->bmihDecomp);
  138.     }
  139.  
  140.     hdd->histo->Zero();
  141.     hdd->histo->Process24(&hdd->vbitmap);
  142.     hdd->histo->Draw(hdd->hdc, &hdd->rHisto);
  143.  
  144. //    if (!hdd->hic) {
  145.         wsprintf(buf, "Histogram: %ld(%ld) frames",capStatus.dwCurrentVideoFrame,capStatus.dwCurrentVideoFramesDropped);
  146.         SendMessage(hdd->hDlg, WM_SETTEXT, 0, (LPARAM)buf);
  147. //    }
  148.  
  149. //    RedrawWindow(hdd->hwndStatus, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
  150.     return 0;
  151. }
  152.  
  153. static void CaptureHistogramDestruct(HWND hwnd, HistogramDlgData *hdd) {
  154.     if (hdd->fParmsSet)
  155.         capCaptureSetSetup(hdd->hwndCapture, &hdd->cp_back, sizeof(CAPTUREPARMS));
  156.  
  157.     freemem(hdd->buffer);
  158.     if (hdd->fCompressionOk)    ICDecompressEnd(hdd->hic);
  159.     if (hdd->hic)                ICClose(hdd->hic);
  160.  
  161.     delete hdd->histo;
  162.     freemem(hdd->bmih);
  163.     if (hdd->hdc) ReleaseDC(hwnd, hdd->hdc);
  164.     capSetCallbackOnFrame(hdd->hwndCapture, (LPVOID)NULL);
  165.     capSetCallbackOnVideoStream(hdd->hwndCapture, (LPVOID)NULL);
  166.     capSetCallbackOnStatus(hdd->hwndCapture, (LPVOID)CaptureStatusCallback);
  167.  
  168.     delete hdd;
  169. }
  170.  
  171. BOOL APIENTRY CaptureHistogramDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam) {
  172.     HistogramDlgData *hdd = (HistogramDlgData *)GetWindowLong(hDlg, DWL_USER);
  173.  
  174.     switch(message) {
  175.         case WM_INITDIALOG:
  176.             try {
  177.                 RECT r, rc;
  178.                 DWORD err;
  179.  
  180.                 ////
  181.  
  182.                 if (!(hdd = new HistogramDlgData)) throw MyError("Out of memory");
  183.                 memset(hdd, 0, sizeof(HistogramDlgData));
  184.  
  185.                 hdd->hDlg = hDlg;
  186.                 hdd->hwndCapture = (HWND)lParam;
  187. //                hdd->hwndStatus = GetDlgItem(GetParent(hdd->hwndCapture), IDC_STATUS_WINDOW);
  188.  
  189.                 if (!(hdd->fsize = capGetVideoFormatSize((HWND)lParam))
  190.                     || !(hdd->bmih = (BITMAPINFOHEADER *)allocmem(hdd->fsize))
  191.                     || !capGetVideoFormat(hdd->hwndCapture, hdd->bmih, hdd->fsize)
  192.                     )
  193.                     throw MyError("Couldn't get video format.");
  194.  
  195.                 memcpy(&hdd->bmihDecomp, hdd->bmih, sizeof(BITMAPINFOHEADER));
  196.                 hdd->bmihDecomp.biSize            = sizeof(BITMAPINFOHEADER);
  197.                 hdd->bmihDecomp.biPlanes        = 1;
  198.                 hdd->bmihDecomp.biBitCount        = 24;
  199.                 hdd->bmihDecomp.biCompression    = BI_RGB;
  200.                 hdd->bmihDecomp.biSizeImage        = ((hdd->bmihDecomp.biWidth*3+3)&-4) * hdd->bmihDecomp.biHeight;
  201.  
  202.                 // allocate screenbuffer
  203.  
  204.                 if (!(hdd->buffer = allocmem(hdd->bmihDecomp.biSizeImage+4))) throw MyError("Out of memory");
  205.  
  206.                 // initialize VirtualBitmap
  207.  
  208.                 hdd->vbitmap.data    = (Pixel *)hdd->buffer;
  209.                 hdd->vbitmap.w        = hdd->bmihDecomp.biWidth;
  210.                 hdd->vbitmap.h        = hdd->bmihDecomp.biHeight;
  211.                 hdd->vbitmap.pitch    = (hdd->bmihDecomp.biWidth*3+3)&-4;
  212.                 hdd->vbitmap.modulo    = hdd->vbitmap.pitch - hdd->vbitmap.w*3;
  213.  
  214.                 SetWindowLong(hDlg, DWL_USER, (DWORD)hdd);
  215.  
  216.                 // resize requester to accommodate histogram
  217.  
  218.                 GetWindowRect(hDlg, &r);
  219.                 GetClientRect(hDlg, &rc);
  220.                 SetWindowPos(hDlg, NULL, 0, 0, (r.right-r.left)-(rc.right-rc.left)+256, (r.bottom-r.top)-(rc.bottom-rc.top)+128, SWP_NOACTIVATE|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  221.  
  222.                 hdd->rHisto.left = hdd->rHisto.top = 0;
  223.                 hdd->rHisto.right = 256;
  224.                 hdd->rHisto.bottom = 128;
  225.  
  226.                 // allocate a Histogram
  227.  
  228.                 if (!(hdd->hdc = GetDC(hDlg)))
  229.                     throw MyError("No display context available");
  230.  
  231.                 if (!(hdd->histo = new Histogram(hdd->hdc, 128)))
  232.                     throw MyError("No histogram!  *sniff*");
  233.  
  234.                 hdd->histo->SetMode(Histogram::MODE_GRAY);
  235.  
  236.                 // change parms
  237.  
  238.                 if (!capCaptureGetSetup(hdd->hwndCapture, &hdd->cp, sizeof(CAPTUREPARMS)))
  239.                     throw MyError("Couldn't get capture parameters");
  240.  
  241.                 hdd->cp_back = hdd->cp;
  242.  
  243.                 hdd->cp.fCaptureAudio            = FALSE;
  244.                 hdd->cp.fMakeUserHitOKToCapture    = FALSE;
  245.                 hdd->cp.fYield                    = TRUE;
  246.                 hdd->cp.vKeyAbort                = 0;
  247.                 hdd->cp.fAbortLeftMouse            = FALSE;
  248.                 hdd->cp.fAbortRightMouse        = FALSE;
  249.                 hdd->cp.wTimeLimit                = FALSE;
  250.                 hdd->cp.fMCIControl                = FALSE;
  251.  
  252.                 if (!capCaptureSetSetup(hdd->hwndCapture, &hdd->cp, sizeof(CAPTUREPARMS)))
  253.                     throw MyError("Couldn't set capture parameters");
  254.  
  255.                 hdd->fParmsSet = TRUE;
  256.  
  257.                 // point capture window to us
  258.  
  259.                 capSetUserData(hdd->hwndCapture, (LPARAM)hdd);
  260.  
  261.                 // send off a timer message to kickstart the op
  262.  
  263.                 capSetCallbackOnStatus(hdd->hwndCapture, (LPVOID)CaptureHistogramStatusCallbackProc);
  264.  
  265.                 if (hdd->bmih->biCompression != BI_RGB) {
  266.  
  267.                     // attempt to find a decompressor
  268.  
  269. //                    hdd->hic = ICLocate('CDIV', NULL, hdd->bmih, NULL/*&hdd->bmihDecomp*/, ICMODE_DECOMPRESS);
  270.                     hdd->hic = ICOpen(ICTYPE_VIDEO, hdd->bmih->biCompression, ICMODE_DECOMPRESS);
  271.                     if (!hdd->hic)
  272.                         hdd->hic = ICLocate(ICTYPE_VIDEO, NULL, hdd->bmih, NULL, ICMODE_DECOMPRESS);
  273.  
  274.                     if (!hdd->hic)
  275.                         throw MyError("Couldn't find a decompressor to 24-bit RGB video");
  276.  
  277.                     if (ICERR_OK != (err = ICDecompressBegin(hdd->hic, hdd->bmih, &hdd->bmihDecomp)))
  278.                         throw MyICError("Failure init'ing decompression", err);
  279.  
  280.                     hdd->fCompressionOk = TRUE;
  281.  
  282.                     capSetCallbackOnFrame(hdd->hwndCapture, (LPVOID)CaptureHistogramVideoCallbackProc);
  283.                     hdd->fCaptureStupid = TRUE;
  284.                     SetTimer(hDlg, 1, 0, NULL);
  285.  
  286.                 } else {
  287.  
  288.                     hdd->fCapture = TRUE;
  289.                     capSetCallbackOnVideoStream(hdd->hwndCapture, (LPVOID)CaptureHistogramVideoCallbackProc);
  290.                     PostMessage(hdd->hwndCapture, WM_CAP_SEQUENCE_NOFILE, 0, 0);
  291.                 }
  292.             } catch(MyError e) {
  293.                 e.post(hDlg,"Histogram error");
  294.  
  295.                 if (hdd) CaptureHistogramDestruct(hDlg, hdd);
  296.  
  297.                 EndDialog(hDlg, FALSE);
  298.             }
  299.             break;
  300.  
  301.         case WM_LBUTTONUP:
  302.             hdd->histo->SetMode(Histogram::MODE_NEXT);
  303.             return TRUE;
  304.  
  305.         case WM_SYSCOMMAND:
  306.             if ((wParam & 0xFFF0) == SC_CONTEXTHELP) {
  307.                 HelpPopup(hDlg, IDH_CAPTURE_HISTOGRAM);
  308.                 return TRUE;
  309.             }
  310.             return FALSE;
  311.  
  312.         case WM_COMMAND:
  313.             if (hdd) {
  314.                 if (hdd->fCapture) {
  315.                     capCaptureStop(hdd->hwndCapture);
  316.                     return TRUE;
  317.                 }
  318.                 CaptureHistogramDestruct(hDlg, hdd);
  319.             }
  320.             EndDialog(hDlg, 0);
  321.             return TRUE;
  322.  
  323.         case WM_TIMER:
  324.             if (hdd->fCaptureStupid)
  325.                 capGrabFrame(hdd->hwndCapture);
  326.  
  327.             return TRUE;
  328.     }
  329.  
  330.     return FALSE;
  331. }
  332.